/*****************************************************************************/
/**
 *  @file   pbvr.comp.cpp
 *  @author Allan Lorant, Naohisa Sakamoto
 */
/*----------------------------------------------------------------------------
 *
 *  Copyright (c) Visualization Laboratory, Kyoto University.
 *  All rights reserved.
 *  See http://www.viz.media.kyoto-u.ac.jp/kvs/copyright/ for details.
 *
 *  $Id$
 */
/*****************************************************************************/
#include "pbvr.comp.h"
#include "MetaModulePixelSend.h"
#include "MetaModulePixelDraw.h"
#include "MetaModuleParticleSend.h"
#include "MetaModuleParticleDraw.h"
#include <flowvr/app/core/genclass.h>
#include <flowvr/app/components/flowvr-app.comp.h>


// Required to enable dynamic component loading
// Argument given in parameter is the class name (respect case) (also requires a pbvr(id) constructor)
GENCLASS( pbvr );


pbvr::pbvr( const std::string id ): pbvr::SuperClass( id )
{
    SuperClass::setInfo( "Distributed Particle-based Volume Rendering on FlowVR" );
    SuperClass::addParameter( "data", "Data file (*.kvsml)" );
    SuperClass::addParameter( "send", "Sending type (pixel or particle)" );
    SuperClass::addParameter( "repeat", "Repetition level (1,4,9,16,25,...)" );
    SuperClass::addParameter( "gpu", "GPU rendering (0:disable,1:enable)" );
    SuperClass::addParameter( "lod", "LOD rendering (0:disable,1:enable)" );
}

flowvr::app::Component* pbvr::create() const
{
    return new pbvr( SuperClass::getId() );
}

void pbvr::execute()
{
    const std::string send = SuperClass::getParameter<std::string>("send");
    if ( send == "pixel" )
    {
        // Meta modules.
        MetaModulePixelSend* pixel_send = SuperClass::addObject<MetaModulePixelSend>("PixelSend");
        MetaModulePixelDraw* pixel_draw = SuperClass::addObject<MetaModulePixelDraw>("PixelDraw");

        // Set arguments.
        pixel_send->getRun()->addArg( flowvr::app::TokenParameter( *this, "data" ).getString() );
        pixel_send->getRun()->addArg( flowvr::app::TokenParameter( *this, "repeat" ).getString() );
        pixel_send->getRun()->addArg( flowvr::app::TokenParameter( *this, "gpu" ).getString() );
        pixel_send->getRun()->addArg( flowvr::app::TokenParameter( *this, "lod" ).getString() );

        // Control loop against overflows.
        typedef flowvr::app::FilterPreSignal PreSignal;
        PreSignal* finished_request = SuperClass::addObject<PreSignal>("PresignalFinishedRequest");
        flowvr::app::link( pixel_draw->getPort("endIt"), finished_request->getPort("in") );
        flowvr::app::link( finished_request->getPort("out"), pixel_send->getPort("beginIt") );

        // Link the modules.
        flowvr::app::link( pixel_send->getPort("pixelOut"), pixel_draw->getPort("pixelIn") );
        flowvr::app::link( pixel_send->getPort("sizeOut"), pixel_draw->getPort("sizeIn") );
    }
    else if ( send == "particle" )
    {
        // Meta modules.
        MetaModuleParticleSend* particle_send = SuperClass::addObject<MetaModuleParticleSend>("ParticleSend");
        MetaModuleParticleDraw* particle_draw = SuperClass::addObject<MetaModuleParticleDraw>("ParticleDraw");

        // Set arguments.
        particle_send->getRun()->addArg( flowvr::app::TokenParameter( *this, "data" ).getString() );
        particle_send->getRun()->addArg( flowvr::app::TokenParameter( *this, "repeat" ).getString() );
        particle_draw->getRun()->addArg( flowvr::app::TokenParameter( *this, "repeat" ).getString() );
        particle_draw->getRun()->addArg( flowvr::app::TokenParameter( *this, "gpu" ).getString() );
        particle_draw->getRun()->addArg( flowvr::app::TokenParameter( *this, "lod" ).getString() );

        // Link the modules.
        flowvr::app::link( particle_send->getPort("particleOut"), particle_draw->getPort("particleIn") );
    }
    else
    {
        std::cout << "Unknown send '" << send << "'" << std::endl;
    }
}
